﻿using CinemaMaestro.ViewModels;
using CinemaMaestro.WindowsApplication.EndPoints;
using MetroFramework;
using MetroFramework.Forms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CinemaMaestro.WindowsApplication.Screening
{
    public partial class ScreeningsForm : MetroForm
    {
        private ScreeningEndPoints endPoints;
        private MovieEndPoints movieEndPoints;
        private LanguageEndPoints languageEndPoints;
        private CinemaEndPoints cinemaEndPoints;
        private RoomEndPoints roomEndPoints;

        private List<ScreeningViewModel> screenings = new List<ScreeningViewModel>();
        private List<MovieViewModel> movies = new List<MovieViewModel>();
        private List<LanguageViewModel> languages = new List<LanguageViewModel>();
        private List<CinemaViewModel> cinemas = new List<CinemaViewModel>();
        private List<RoomViewModel> rooms = new List<RoomViewModel>();

        private int selectedRoomId = -1;

        public ScreeningsForm(HttpClient client)
        {
            this.endPoints = new ScreeningEndPoints(client);
            this.movieEndPoints = new MovieEndPoints(client);
            this.languageEndPoints = new LanguageEndPoints(client);
            this.cinemaEndPoints = new CinemaEndPoints(client);
            this.roomEndPoints = new RoomEndPoints(client);

            InitializeComponent();
            ScreeningsFormToInitialState();

            PopulateScreeningsListView();
            PopulateMoviesComboBox();
            PopulateLanguagesComboBox();
            PopulateCinemasComboBox();
        }

        private void ScreeningsForm_MouseDown(object sender, MouseEventArgs e)
        {
            ScreeningsFormToInitialState();
        }

        private void clearButton_Click(object sender, EventArgs e)
        {
            ScreeningsFormToInitialState();
        }

        private void ScreeningsFormToInitialState()
        {
            startDayDateTime.Text = String.Empty;
            priceUpDown.Text = String.Empty;
            priceUpDown.Value = 0;
            discountPriceUpDown.Text = String.Empty;
            discountPriceUpDown.Value = 0;
            availableTimeSlotsComboBox.SelectedIndex = -1;
            movieComboBox.SelectedIndex = -1;
            languageComboBox.SelectedIndex = -1;
            cinemaComboBox.SelectedIndex = -1;
            roomComboBox.SelectedIndex = -1;
            roomComboBox.Enabled = false;
            availableTimeSlotsComboBox.Enabled = false;
            addButton.Enabled = true;
            deleteButton.Enabled = false;
            updateButton.Enabled = false;
            screeningsListView.SelectedIndices.Clear();
        }

        private async void PopulateScreeningsListView()
        {
            screeningsListView.Items.Clear();
            try
            {
                screenings = await endPoints.GetAllScreeningsAsync();
                foreach (var screening in screenings)
                {
                    var item = new ListViewItem();
                    item.Text = screening.Id.ToString();
                    item.SubItems.Add(screening.StartDate.ToShortDateString());
                    item.SubItems.Add(screening.Movie.Title);
                    item.SubItems.Add(screening.Language.Name);
                    item.SubItems.Add(screening.Room.Name);
                    item.SubItems.Add(screening.Room.Cinema.Name);
                    screeningsListView.Items.Add(item);
                }
            }
            catch
            {
                MetroMessageBox.Show(this, "Cannot retrieve screenings!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }

        private void screeningsListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (screeningsListView.SelectedItems.Count == 1)
            {
                deleteButton.Enabled = true;
                updateButton.Enabled = true;
                addButton.Enabled = false;

                int id = Int32.Parse(screeningsListView.SelectedItems[0].SubItems[0].Text);
                var selectedScreening = screenings.First(x => x.Id == id);

                availableTimeSlotsComboBox.SelectedIndex = -1;
                startDayDateTime.Value = selectedScreening.StartDate;
                priceUpDown.Text = selectedScreening.Price.ToString(".##");
                discountPriceUpDown.Text = selectedScreening.DiscountedPrice.ToString(".##");

                cinemaComboBox.SelectedItem = cinemas.FirstOrDefault(x => x.Id == selectedScreening.Room.Cinema.Id);
                movieComboBox.SelectedItem = movies.FirstOrDefault(x => x.Id == selectedScreening.Movie.Id);
                languageComboBox.SelectedItem = languages.FirstOrDefault(x => x.Id == selectedScreening.Language.Id);                
            }
        }

        private async void PopulateMoviesComboBox()
        {
            movieComboBox.Items.Clear();
            try
            {
                movies = await movieEndPoints.GetAllMoviesAsync();
                foreach (var movie in movies)
                {
                    movieComboBox.Items.Add(movie);
                }
            }
            catch
            {
                MetroMessageBox.Show(this, "Cannot retrieve movies!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }

        private async void PopulateLanguagesComboBox()
        {
            languageComboBox.Items.Clear();
            try
            {
                languages = await languageEndPoints.GetAllLanguagesAsync();
                foreach (var language in languages)
                {
                    languageComboBox.Items.Add(language);
                }
            }
            catch
            {
                MetroMessageBox.Show(this, "Cannot retrieve languages!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }

        private async void PopulateCinemasComboBox()
        {
            cinemaComboBox.Items.Clear();
            try
            {
                cinemas = await cinemaEndPoints.GetAllCinemasAsync();
                foreach (var cinema in cinemas)
                {
                    cinemaComboBox.Items.Add(cinema);
                }
            }
            catch
            {
                MetroMessageBox.Show(this, "Cannot retrieve cinemas!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }

        private async void PopulateRoomsComboBox(int cinemaId)
        {
            roomComboBox.Items.Clear();
            try
            {
                rooms = await roomEndPoints.GetAllRoomsForCinemaAsync(cinemaId);
                foreach (var room in rooms)
                {
                    roomComboBox.Items.Add(room);
                }
               
                if (screeningsListView.SelectedItems.Count > 0)
                {
                    int id = Int32.Parse(screeningsListView.SelectedItems[0].SubItems[0].Text);
                    var selectedScreening = screenings.First(x => x.Id == id);
                    roomComboBox.SelectedItem = rooms.FirstOrDefault(x => x.Id == selectedScreening.Room.Id);
                }
            }
            catch
            {
                MetroMessageBox.Show(this, "Cannot retrieve rooms!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }

        private void cinemaComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cinemaComboBox.SelectedIndex > -1)
            {
                roomComboBox.Enabled = true;
                roomComboBox.SelectedIndex = -1;
                var selectedId = ((CinemaViewModel)cinemaComboBox.SelectedItem).Id;
                PopulateRoomsComboBox(selectedId);
            }
            else
            {
                roomComboBox.Enabled = false;
                roomComboBox.SelectedIndex = -1;
            }
        }

        private async void PopulateAvailableTimeSlots(int roomId, DateTime startDate, int movieId)
        {
            availableTimeSlotsComboBox.Items.Clear();
            try
            {
                var startTimes = await endPoints.GetAvailableStartTimesAsync(roomId, startDate, movieId);
                foreach (var time in startTimes)
                {
                    availableTimeSlotsComboBox.Items.Add(time);
                }
            }
            catch
            {
                MetroMessageBox.Show(this, "Cannot retrieve available start times!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }

        private void roomComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (roomComboBox.SelectedIndex > -1 && movieComboBox.SelectedIndex > -1)
            {
                availableTimeSlotsComboBox.Enabled = true;
                availableTimeSlotsComboBox.SelectedIndex = -1;
                var selectedRoomId = ((RoomViewModel)roomComboBox.SelectedItem).Id;
                var selectedMovieId = ((MovieViewModel)movieComboBox.SelectedItem).Id;
                PopulateAvailableTimeSlots(selectedRoomId, startDayDateTime.Value, selectedMovieId);
                if (screeningsListView.SelectedItems.Count > 0)
                {
                    int id = Int32.Parse(screeningsListView.SelectedItems[0].SubItems[0].Text);
                    var selectedScreening = screenings.First(x => x.Id == id);
                    if (((RoomViewModel)roomComboBox.SelectedItem).Id == selectedScreening.Room.Id
                        && ((MovieViewModel)movieComboBox.SelectedItem).Id == selectedScreening.Movie.Id)
                    {
                        TimeSpan currentStartTime = selectedScreening.StartDate.TimeOfDay;
                        availableTimeSlotsComboBox.Items.Add(currentStartTime);
                        availableTimeSlotsComboBox.SelectedItem = currentStartTime;
                    }
                }  
            }
            else
            {
                availableTimeSlotsComboBox.Enabled = false;
                availableTimeSlotsComboBox.SelectedIndex = -1;
            }
        }

        private void movieComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (movieComboBox.SelectedIndex > -1 && roomComboBox.SelectedIndex > -1)
            {
                availableTimeSlotsComboBox.Enabled = true;
                availableTimeSlotsComboBox.SelectedIndex = -1;
                var selectedRoomId = ((RoomViewModel)roomComboBox.SelectedItem).Id;
                var selectedMovieId = ((MovieViewModel)movieComboBox.SelectedItem).Id;
                PopulateAvailableTimeSlots(selectedRoomId, startDayDateTime.Value, selectedMovieId);
                if (screeningsListView.SelectedItems.Count > 0)
                {
                    int id = Int32.Parse(screeningsListView.SelectedItems[0].SubItems[0].Text);
                    var selectedScreening = screenings.First(x => x.Id == id);
                    if (((RoomViewModel)roomComboBox.SelectedItem).Id == selectedScreening.Room.Id
                        && ((MovieViewModel)movieComboBox.SelectedItem).Id == selectedScreening.Movie.Id)
                    {
                        TimeSpan currentStartTime = selectedScreening.StartDate.TimeOfDay;
                        availableTimeSlotsComboBox.Items.Add(currentStartTime);
                        availableTimeSlotsComboBox.SelectedItem = currentStartTime;
                    }
                }    
            }
            else
            {
                availableTimeSlotsComboBox.Enabled = false;
                availableTimeSlotsComboBox.SelectedIndex = -1;
            }
        }

        private bool ValidateScreening()
        {
            if (priceUpDown.Text == String.Empty)
            {
                MetroMessageBox.Show(this, "Please provide a price for the Screening!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }
            if (discountPriceUpDown.Text == String.Empty)
            {
                MetroMessageBox.Show(this, "Please provide a discount price for the Screening!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }
            if (movieComboBox.SelectedIndex == -1)
            {
                MetroMessageBox.Show(this, "Please select a Movie!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }
            if (languageComboBox.SelectedIndex == -1)
            {
                MetroMessageBox.Show(this, "Please select a Language!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }
            if (roomComboBox.SelectedIndex == -1)
            {
                MetroMessageBox.Show(this, "Please select a Room!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }
            if (availableTimeSlotsComboBox.SelectedIndex == -1)
            {
                MetroMessageBox.Show(this, "Please select a start time!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return false;
            }
            return true;
        }

        private async void addButton_Click(object sender, EventArgs e)
        {
            if (ValidateScreening())
            {
                try
                {
                    var selectedTime = (TimeSpan)availableTimeSlotsComboBox.SelectedItem;
                    var date = startDayDateTime.Value;
                    var startDate = new DateTime(date.Year, date.Month, date.Day, selectedTime.Hours, selectedTime.Minutes, selectedTime.Seconds);
                    var movie = (MovieViewModel)movieComboBox.SelectedItem;
                    var language = (LanguageViewModel)languageComboBox.SelectedItem;
                    var room = (RoomViewModel)roomComboBox.SelectedItem;

                    var screening = new ScreeningViewModel
                    {
                        Price = Double.Parse(priceUpDown.Value.ToString()),
                        DiscountedPrice = Double.Parse(discountPriceUpDown.Value.ToString()),
                        StartDate = startDate,
                        EndDate = startDate.AddMinutes(movie.Duration),
                        Movie = movie,
                        Language = language,
                        Room = room
                    };
                    await endPoints.CreateScreeningAsync(screening);
                }
                catch
                {
                    MetroMessageBox.Show(this, "Cannot create screening!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                }
                finally
                {
                    PopulateScreeningsListView();
                    ScreeningsFormToInitialState();
                }
            }
        }

        private async void updateButton_Click(object sender, EventArgs e)
        {
            if (ValidateScreening())
            {
                try
                {
                    var selectedTime = (TimeSpan)availableTimeSlotsComboBox.SelectedItem;
                    var date = startDayDateTime.Value;
                    var startDate = new DateTime(date.Year, date.Month, date.Day, selectedTime.Hours, selectedTime.Minutes, selectedTime.Seconds);
                    var movie = (MovieViewModel)movieComboBox.SelectedItem;
                    var language = (LanguageViewModel)languageComboBox.SelectedItem;
                    var room = (RoomViewModel)roomComboBox.SelectedItem;
                    int selectedId = Int32.Parse(screeningsListView.SelectedItems[0].SubItems[0].Text);

                    var screening = new ScreeningViewModel
                    {
                        Id = selectedId,
                        Price = Double.Parse(priceUpDown.Value.ToString()),
                        DiscountedPrice = Double.Parse(discountPriceUpDown.Value.ToString()),
                        StartDate = startDate,
                        EndDate = startDate.AddMinutes(movie.Duration),
                        Movie = movie,
                        Language = language,
                        Room = room
                    };
                    await endPoints.UpdateScreeningAsync(screening);
                }
                catch
                {
                    MetroMessageBox.Show(this, "Cannot create screening!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                }
                finally
                {
                    PopulateScreeningsListView();
                    ScreeningsFormToInitialState();
                }
            }
        }

        private async void deleteButton_Click(object sender, EventArgs e)
        {
            try
            {
                int selectedId = Int32.Parse(screeningsListView.SelectedItems[0].SubItems[0].Text);
                await endPoints.DeleteScreeningAsync(selectedId);
            }
            catch
            {
                MetroMessageBox.Show(this, "Cannot delete screening!", String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
            finally
            {
                PopulateScreeningsListView();
                ScreeningsFormToInitialState();
            }   
        }

    }
}
